easy接口的选项的配置
3 curl_easy_setopt()
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLoption option, parameter);
这个接口是用来定制发送细节的,我们大部分逻辑需要通过这个接口传给“curl easy handle”在下一步的curl_easy_perform()
中进行传输。
定制请求行 --- CURLOPT_URL
#include <curl/curl.h>
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL);
该选项CURLOPT_URL
用来设置请求行。该选项是 唯一必须 设置的选项。
其中URL
需遵循以下格式:
[scheme://]host[:port]/path
libcurl 不会对传入的url
进行验证,因此即使传入的是一个很离谱的字符串,接口的返回值也一样会是CURLE_OK
。
scheme
如果传入的URL
没有定义scheme
,那么libcurl
会根据host
进行猜测,如果host
的域名符合DICT
, FTP
, IMAP
, LDAP
, POP3
或者 SMTP
,那么对应的scheme
会被使用,否则的话,会用http
。默认的scheme
可以用CURLOPT_DEFAULT_PROTOCOL
进行定义。
如果scheme
中设置的协议不是libcurl所支持的,那么在后续的调用curl_easy_perform
会返回CURLE_UNSUPPORTED_PROTOCOL
。
host
host
部分包含需要访问的服务地址,可以是hostname也可以是IP,对于一些类型的协议,可以用以下格式指定用户名和密码:
scheme:\\user:password;options@host:port\path
port
port
部分为可选配置,如果不设置的话,libcurl会根据协议的类型来选择端口,如http
默认使用80端口。
另外,开发者还可以使用CURLOPT_PORT
来指定端口。
定制HTTP方法 --- CURLOPT_HTTPGET
,CURLOPT_PUT
,CURLOPT_POST
,CCURLOPT_UPLOAD
这三个选项用来指定http请求的方法,需要注意的是Get
方法的字符和其他方法的格式有所不同。
需要使用某种方法时,需将其选项置为1L
(long)。如:
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
CURLOPT_HTTPGET
,配置发送http Get
请求,若被置为1,则CURLOPT_UPLOAD
和CURLOPT_NOBODY
会被自动置成0.
CURLOPT_POST
,配置发送http Post
请求。
CURLOPT_PUT
在最新版本中已经被弃用,替代版本是CURLOPT_UPLOAD
。
在HTTP1.1
中,可以通过块传输的方式来传输文件或者数据,在这种情况下,无需指定文件的大小。(需要指定http头Transfer-Encoding: chunked
)
如果采用其他方式,或者使用HTTP1.0
,则必须指定文件大小。
定制HTTP头部 --- CURLOPT_HTTPHEADER
以发送http请求为例,如果我们想在在发送的请求中带上一些http头,那么我们就需要调用:
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTPHEADER, struct curl_slist *headers);
使用CURLOPT_HTTPHEADER
的option,把定制的http头放在struct curl_slist *headers
中。
关于struct curl_slist *headers
,curl提供了一组API进行操作:
curl_slist_append()
curl_slist_free_all()
#include <curl/curl.h>
struct curl_slist *curl_slist_append(struct curl_slist * list, const char * string );
该接口用来向curl_slist
添加新的项目。比如说,我想添加一个自定义的头“x-hello-world”,对应的代码应该是如下:
struct curl_slist* slist = NULL;
slist = curl_slist_append(slist, "x-hello-world: 1");
这样,最终发出来的报文中就会包含x-hello-world:1
头,如果在这一步中设置了一个默认的http头,那么这个定制的头会覆盖默认的http头。
如果在这步设置了一个不完整的http头(这个头默认是存在的),如:Accept:
(缺少数据),那么这个头会被在报文中被去掉。
如果想加一个没有内容的http头,需要使用这样的格式:MyHeader;
。
这些添加的头不能以\r\n
(CRLF)结尾,因为在添加的过程中,函数会自动地给每个头加上\r\n
。
请求行需要用3.1
中介绍的CURLOPT_URL
进行设置。
另外一个接口:
#include <curl/curl.h>
void curl_slist_free_all(struct curl_slist * list);
这个接口用来释放一个curl_slist
中所有的节点。
需要注意的是,在整个请求的发送过程中,该链表的内存会被libcurl直接使用,所有只有在传输全部完成的情况下,才可以调用curl_slist_free_all()
释放该链表的内存。
上传文件
上传文件时需要用到:
CURLOPT_READFUNCTION
CURLOPT_READDATA
其中,CURLOPT_READFUNCTION
用来指定设置http body
时的回调函数,该函数需要开发者实现,需要遵守如下原型:
size_t read_callback(char* buffer, size_t size, size_t nitems, void* instream);
该回调函数表明,要从源instream
向目标缓冲buffer
中写入size * nitems bytes
的数据。
前三个参数由libcurl在curl_easy_perform
过程中输入,最后一个参数往往是输入的数据源,使用CURLOPT_READDATA
选项进行设置。
回调函数的返回值表示此次实际读取的数据大小,如果返回0的话,会向libcurl
库发生EOF
的信号,这会停止当前的传输过程。
如果试图直接返回0
值来使手动停止当前传输过程,服务端对应的处理程序会Hung
住,因为服务端并没有收到指定的数据量。
正确的停止当前传输过程的方法是返回CURL_READFUNC_ABORT
。
使用SSL
配置使用SSL时,需要用到CURLOPT_SSLVERSION
来指定SSL的版本,目前使用CURL_SSLVERSION_TLSv1
。
同时,如果使用的是自签名的证书,需要把CURLOPT_SSL_VERIFYPEER
和CURLOPT_SSL_VERIFYHOST
都置成0L。这样的话,使用自定义的证书进行SSL连接的时候,就不会检测证书是否是正规CA颁发的,也不会检查该证书是否是颁发给该host的。
如果想要在非http协议中使用SSL,需要设置CURLOPT_USE_SSL
来进行配置。
使用代理
如果想要在连接中使用代理,需要设置下列选项中的一个或者多个:
CURLOPT_PROXY
CURLOPT_PROXYPORT
CURLOPT_PROXYTYPE
CURLOPT_PROXY
选项用来指定代理的地址,其scheme格式类似CURLOPT_URL
的规定,可以在其中指定协议类型,host,端口,用户名密码等。
如果不希望在这个scheme中指定太多内容的话,则需要其他选项来进行配置。
在代理有密码的情况下,如果不希望把密码直接写在代理地址的scheme中,则需要设置:
CURLOPT_PROXYUSERPWD
其scheme为 [user]:[password]
。
接受数据
接受数据需要配置如下选项:
CURLOPT_WRITEFUNCTION
CURLOPT_WRITEDATA
配置CURLOPT_WRITEFUNCTION
来指定处理接受到的数据的回调函数,该回调函数需要遵循如下原型:
size_t write_callback(char * ptr, size_t size, size_t nmemb, void * userdata);
其中ptr
指向接收到数据的内存,该数据的大小为size * nmemb bytes
,第四个参数userdata
使用CURLOPT_WRITEDATA
来指定。
需要指出的是,在windows环境下,如果设置了CURLOPT_WRITEDATA
,则必须设置CURLOPT_WRITEFUNCTION
,否则会导致程序崩溃。
CURLOPT_WRITEFUNCTION
主要用来接收报文Body
的数据,但这里的Body
范围是可定义的。通过设置选项CURLOPT_HEADER
为1,可以把所有header
数据放到body
中进行处理。
打开调试模式
CURLOPT_VERBOSE
将此项设置为1时,打开详细调试模式。默认情况下,调试信息会被发送到标准错误(stderr),可以使用CURLOPT_STDERR
设置标准输出。 如果需要所有协议的发送和接收的详情,需要设置CURLOPT_DEBUGFUNCTION
。CURLOPT_DEBUGFUNCTION
#include <curl/curl.h>
typedef enum {
CURLINFO_TEXT = 0,
CURLINFO_HEADER_IN, /*1*/
CURLINFO_HEADER_OUT, /*2*/
CURLINFO_DATA_IN, /*3*/
CURLINFO_DATA_OUT, /*4*/
CURLINFO_SSL_DATA_IN, /*5*/
CURLINFO_SSL_DATA_OUT, /*6*/
CURLINFO_END
} curl_infotype;
int debug_callback(CURL* handle,
curl_infotype type,
char* data,
size_t size,
void* userptr);
使用CURLOPT_DEBUGFUNCTION
时,需要提供一个回调函数,其原型如上所示。只有CURLOPT_VERBOSE
被设置的情况下,该回调函数才会取代默认的调试函数起作用。
其参数curl_infotype type
会提供当前阶段的信息。
char* data
是一个不以\0
结尾的字符串,其大小为参数size_t size
中所指定的大小。
该函数必须返回0(CURLE_OK
)。
杂项
CURLOPT_NOSIGNAL
如果将该项设为1,libcurl就不会使用一类函数---任何设有信号处理函数或者可能会收到信号的函数。CURLOPT_CONNECTTIMEOUT
正如该选项名字所示,该选项用来设置建立连接的超时时间。该选项不会对已经建立的连接有任何影响。 如果设其为0,则使用默认值---300秒CURLOPT_TIMEOUT
用来定义传输过程的超时时间。如果设其为0,则永不超时。